#include "ls_wifi_sta.h"
#include "ls_common.h"
#include "ls_config_file.h"
#include "wifi_mgmr_ext.h"
#include "wifi_mgmr.h"
#include "bl616_glb.h"
#include "bl_fw_api.h"


#define DBG_TAG "WIFI"
#include "ls_trace_common.h"



#define WIFI_STACK_SIZE  (1536)
#define TASK_PRIORITY_FW (15)
static TaskHandle_t wifi_fw_task;

static wifi_conf_t conf = {
    .country_code = "CN",
};


wifi_connect_cb  status_cb;
TimerHandle_t    wifi_timeId=NULL;
volatile uint8_t wifi_scan_timer = 0;
extern wifi_mgmr_t wifiMgmr;
extern Ring_Buffer_Type shell_rb;
extern void shell_release_sem(void);
static char wifi_conenct[128];

inline int scan_item_is_timeout(wifi_mgmr_t *mgmr, wifi_mgmr_scan_item_t *item)
{
    return ((unsigned int)rtos_now(0) - (unsigned int)item->timestamp_lastseen) >= mgmr->scan_item_timeout ? 1 : 0;
}


int wifi_mgmr_sta_scanlist(void)
{
    int i;
    wifi_scan_timer = 0;
    printf("****************************************************************************************************\r\n");
    for (i = 0; i < sizeof(wifiMgmr.scan_items)/sizeof(wifiMgmr.scan_items[0]); i++) {
        if (wifiMgmr.scan_items[i].is_used && (!scan_item_is_timeout(&wifiMgmr, &wifiMgmr.scan_items[i]))) 
        {
            printf("index[%02d]: channel %02u, bssid %02X:%02X:%02X:%02X:%02X:%02X, rssi %3d, ppm abs:rel %3d : %3d, wps %2d, mode %6s, auth %20s, cipher:%12s, SSID %s\r\n",
                    i,
                    wifiMgmr.scan_items[i].channel,
                    wifiMgmr.scan_items[i].bssid[0],
                    wifiMgmr.scan_items[i].bssid[1],
                    wifiMgmr.scan_items[i].bssid[2],
                    wifiMgmr.scan_items[i].bssid[3],
                    wifiMgmr.scan_items[i].bssid[4],
                    wifiMgmr.scan_items[i].bssid[5],
                    wifiMgmr.scan_items[i].rssi,
                    wifiMgmr.scan_items[i].ppm_abs,
                    wifiMgmr.scan_items[i].ppm_rel,
                    wifiMgmr.scan_items[i].wps,
                    wifi_mgmr_mode_to_str(wifiMgmr.scan_items[i].mode),
                    wifi_mgmr_auth_to_str(wifiMgmr.scan_items[i].auth),
                    wifi_mgmr_cipher_to_str(wifiMgmr.scan_items[i].cipher),
                    wifiMgmr.scan_items[i].ssid
            );

            char ssid[64];
            char passwd[64];
            if(ls_config_get_wifi(ssid,passwd) == 0 && strcmp(ssid,wifiMgmr.scan_items[i].ssid) == 0)
            {
                snprintf(wifi_conenct,sizeof(wifi_conenct),LS_WIFI_CONNECT_CMD" %s %s \r\n",ssid,passwd);
                Ring_Buffer_Write(&shell_rb, wifi_conenct,strlen(wifi_conenct));
                shell_release_sem();
                if(wifi_timeId)
                xTimerDelete(wifi_timeId,portMAX_DELAY);
                wifi_timeId =NULL;
                return 0;
            }
        }
    }
    printf("****************************************************************************************************\r\n");
    wifi_scan_timer = 1;
    return 0;
}




static void Wifi_TimerCallback( TimerHandle_t xTimer )
{
    if(wifi_scan_timer)
    {
        LS_TRACE_DEBUG("start scan wifi...");
        wifi_mgmr_scan_params_t config;
        memset(&config, 0 , sizeof(wifi_mgmr_scan_params_t));
        int ret = wifi_mgmr_sta_scan(&config);
        if (ret < 0) {
            LS_TRACE_ERROR("scan failed \r\n");
            return;
        }

    }
}


/// @brief wifi 回调
/// @param code 
void wifi_event_handler(uint32_t code)
{
    uint32_t ret = 0;
    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    switch (code) {
        case CODE_WIFI_ON_INIT_DONE: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_INIT_DONE");
            wifi_mgmr_init(&conf);

        } break;
        case CODE_WIFI_ON_MGMR_DONE: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_MGMR_DONE");
            if(status_cb)status_cb(WIFI_INIT_DONE);
        } break;
        case CODE_WIFI_ON_SCAN_DONE: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_SCAN_DONE");
            wifi_mgmr_sta_scanlist();
        } break;
        case CODE_WIFI_ON_CONNECTED: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_CONNECTED");
            void mm_sec_keydump();
            mm_sec_keydump();
            //存储wifi
            wifi_mgmr_connect_ind_stat_info_t wifiinfo;
            wifi_mgmr_sta_connect_ind_stat_get(&wifiinfo);
            LS_TRACE_DEBUG("ssid:%s, pass:%s",wifiinfo.ssid,wifiinfo.passphr);
            ls_config_set_wifi(wifiinfo.ssid,wifiinfo.passphr);
        } break;
        case CODE_WIFI_ON_GOT_IP: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_GOT_IP");
            if(status_cb)status_cb(WIFI_CONENCT_OK);
        } break;
        case CODE_WIFI_ON_DISCONNECT: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_DISCONNECT");
            wifi_scan_timer = 1;
        } break;
        case CODE_WIFI_ON_AP_STARTED: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_AP_STARTED");
        } break;
        case CODE_WIFI_ON_AP_STOPPED: {
            LS_TRACE_DEBUG("CODE_WIFI_ON_AP_STOPPED");
        } break;
        case CODE_WIFI_ON_AP_STA_ADD: {
            LS_TRACE_DEBUG("[APP] [EVT] [AP] [ADD] %lld", xTaskGetTickCount());
        } break;
        case CODE_WIFI_ON_AP_STA_DEL: {
            LS_TRACE_DEBUG("[APP] [EVT] [AP] [DEL] %lld", xTaskGetTickCount());
        } break;
        default: {
            LS_TRACE_DEBUG("[APP] [EVT] Unknown code %u", code);
        }
    }
}



/// @brief 
/// @param ssid 
/// @param password 
void ls_wifi_sta_connect(char *ssid, char *password)
{
    int opt;
    int bssid_set_flag = 0;
    char bssid[18] = {0};

    const char *akm = NULL;
    int pmf_cfg = 1;
    int use_dhcp = 1;

    uint8_t channel_index = 0;
    uint16_t freq = 0;
    uint8_t quick_connect = 0;

    printf("connect wifi ssid:%s, psk:%s, bssid:%d, q:%d\r\n",ssid, password, bssid_set_flag, quick_connect);

    freq = phy_channel_to_freq(PHY_BAND_2G4, channel_index);
    if (quick_connect) {
        wifi_mgmr_sta_connect_params_t conn_param;
        memset(&conn_param, 0, sizeof(conn_param));
        strncpy((char *)conn_param.ssid,ssid, MGMR_SSID_LEN);
        conn_param.ssid_len = strlen((char *)conn_param.ssid);

        if (password) {
          strncpy((char *)conn_param.key, password, MGMR_KEY_LEN);
          conn_param.key_len = strlen((char *)conn_param.key);
        }
        conn_param.freq1 = freq;
        conn_param.freq2 = 0;
        conn_param.use_dhcp = 1;
        conn_param.pmf_cfg = 1;
        conn_param.quick_connect = 1;
        wifi_mgmr_sta_connect(&conn_param);
    } 
    else
    {
        wifi_sta_connect(ssid, password, bssid_set_flag ? bssid : NULL, (char *)akm, pmf_cfg, freq, freq, use_dhcp);
    }
}



int ls_wifi_sta_init(wifi_connect_cb l)
{
    status_cb = l;
    LS_TRACE_DEBUG("Starting wifi ...\r\n");
    /* enable wifi clock */

    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_IP_WIFI_PHY | GLB_AHB_CLOCK_IP_WIFI_MAC_PHY | GLB_AHB_CLOCK_IP_WIFI_PLATFORM);
    GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_WIFI);

    /* set ble controller EM Size */

    GLB_Set_EM_Sel(GLB_WRAM160KB_EM0KB);

    if (0 != rfparam_init(0, NULL, 0)) {
        LS_TRACE_DEBUG("PHY RF init failed!\r\n");
        return 0;
    }

    LS_TRACE_DEBUG("PHY RF init success!\r\n");

    /* Enable wifi irq */
    
    extern void interrupt0_handler(void);
    bflb_irq_attach(WIFI_IRQn, (irq_callback)interrupt0_handler, NULL);
    bflb_irq_enable(WIFI_IRQn);

    xTaskCreate(wifi_main, (char *)"fw", WIFI_STACK_SIZE, NULL, TASK_PRIORITY_FW, &wifi_fw_task);
    
    wifi_scan_timer = 0;
    wifi_timeId = xTimerCreate("wifi daemon",10000,pdTRUE,(void*)1,Wifi_TimerCallback);
    xTimerStart(wifi_timeId,1000);
    return 0;
}